package com.dtyunxi.gateway.config;

import com.dtyunxi.gateway.access.CustomReactiveAuthorizationManager;
import com.dtyunxi.gateway.handle.AuthenticationCallbackHandle;
import com.dtyunxi.gateway.pojo.constant.AuthConstant;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.convert.converter.Converter;
import org.springframework.security.authentication.AbstractAuthenticationToken;
import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity;
import org.springframework.security.config.web.server.ServerHttpSecurity;
import org.springframework.security.oauth2.jwt.Jwt;
import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationConverter;
import org.springframework.security.oauth2.server.resource.authentication.JwtGrantedAuthoritiesConverter;
import org.springframework.security.oauth2.server.resource.authentication.ReactiveJwtAuthenticationConverterAdapter;
import org.springframework.security.web.server.SecurityWebFilterChain;
import reactor.core.publisher.Mono;

@Configuration
@EnableWebFluxSecurity
public class ResourceServerConfiguration {

    @Bean
    public SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) {
        AuthenticationCallbackHandle authenticationCallbackHandle=new AuthenticationCallbackHandle();

        ServerHttpSecurity.AuthorizeExchangeSpec.Access anyExchange = http.authorizeExchange().anyExchange();
        anyExchange.denyAll();
        CustomReactiveAuthorizationManager customAuthorizationManager=new CustomReactiveAuthorizationManager();
        anyExchange.access(customAuthorizationManager);

        //已自定义策略
        http.csrf().disable();
        http.httpBasic().disable();
        http.headers().hsts().includeSubdomains(true);

        http.oauth2ResourceServer().authenticationEntryPoint(authenticationCallbackHandle);
        http.authorizeExchange()
                .and()
                .exceptionHandling()
                //处理未授权
                .accessDeniedHandler(authenticationCallbackHandle)
                //处理未认证
                .authenticationEntryPoint(authenticationCallbackHandle);

        return http.build();
    }

    @Bean
    public Converter<Jwt, ? extends Mono<? extends AbstractAuthenticationToken>> jwtAuthenticationConverter() {
        JwtGrantedAuthoritiesConverter jwtGrantedAuthoritiesConverter = new JwtGrantedAuthoritiesConverter();
        jwtGrantedAuthoritiesConverter.setAuthorityPrefix(AuthConstant.AUTHORITY_PREFIX);
        jwtGrantedAuthoritiesConverter.setAuthoritiesClaimName(AuthConstant.AUTHORITY_CLAIM_NAME);
        JwtAuthenticationConverter jwtAuthenticationConverter = new JwtAuthenticationConverter();
        jwtAuthenticationConverter.setJwtGrantedAuthoritiesConverter(jwtGrantedAuthoritiesConverter);
        return new ReactiveJwtAuthenticationConverterAdapter(jwtAuthenticationConverter);
    }

}